package com.tiancheng.trade.payment.channel.gaocheng;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.tiancheng.commom.pay.PayOrderAutoQueryConfig;
import com.tiancheng.commom.pay.gaocheng.GcPayChannel;
import com.tiancheng.commom.pay.gaocheng.GcPayProperties;
import com.tiancheng.commom.pay.gaocheng.GcSignUtils;
import com.tiancheng.commom.pay.gaocheng.req.GcBasePayReq;
import com.tiancheng.commom.pay.gaocheng.req.pay.*;
import com.tiancheng.commom.pay.gaocheng.res.*;
import com.tiancheng.trade.commom.core.data.Result;
import com.tiancheng.trade.commom.core.enums.PaymentChannelEnum;
import com.tiancheng.trade.commom.core.enums.PaymentWayEnum;
import com.tiancheng.trade.commom.core.exception.Asserts;
import com.tiancheng.trade.commom.core.exception.BusinessException;
import com.tiancheng.trade.commom.core.exception.error.BusinessErrorInfoEnum;
import com.tiancheng.trade.commom.core.utils.AmountUtils;
import com.tiancheng.trade.commom.core.utils.JsonUtil;
import com.tiancheng.trade.commom.web.feign.MerchantFeignService;
import com.tiancheng.trade.commom.core.utils.ForestHttpUtil;
import com.tiancheng.trade.commom.web.model.request.MerchantChannelRequestDTO;
import com.tiancheng.trade.commom.web.model.response.MerchantChannelResponseDTO;
import com.tiancheng.trade.commom.web.model.response.SettlementRuleResVO;
import com.tiancheng.trade.commom.core.utils.DateTimeUtil;
import com.tiancheng.trade.payment.channel.AbstractPayChannel;
import com.tiancheng.trade.payment.channel.bo.*;
import com.tiancheng.trade.payment.channel.bo.paybo.AlipayResBO;
import com.tiancheng.trade.payment.channel.bo.paybo.CorpPayRes;
import com.tiancheng.trade.payment.channel.bo.paybo.WechatPayResBO;
import com.tiancheng.trade.payment.channel.enums.ChannelOrderStatusEnum;
import com.tiancheng.trade.payment.channel.ums.params.UmsUnifiedOrderParam;
import com.tiancheng.trade.payment.enums.ChannelRefundTypeEnum;
import com.tiancheng.trade.payment.mapper.PaymentFlowDetailMapper;
import com.tiancheng.trade.payment.mapper.PaymentOrderMapper;
import com.tiancheng.trade.payment.mapper.PaymentRefundFlowDetailMapper;
import com.tiancheng.trade.payment.mapper.PaymentRefundFlowMapper;
import com.tiancheng.trade.payment.model.*;
import com.tiancheng.trade.payment.service.PaymentMerchantPlatformService;
import com.tiancheng.trade.payment.service.SettlePlatformService;
import com.tiancheng.trade.payment.util.CommonUtil;
import com.tiancheng.trade.payment.util.ObjectConvertUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.message.BasicHeader;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 高城支付中台
 */
@Slf4j
@Service
public class GaoChengChannel implements AbstractPayChannel {

    @Resource
    private GcPayConfig gcPayConfig;
    @Resource
    private PaymentOrderMapper paymentOrderMapper;
    @Resource
    private PaymentRefundFlowMapper paymentRefundFlowMapper;
    @Resource
    private PaymentRefundFlowDetailMapper refundFlowDetailMapper;
    @Resource
    private PaymentFlowDetailMapper paymentFlowDetailMapper;
    @Resource
    private SettlePlatformService settlePlatformService;
    @Resource
    private MerchantFeignService merchantFeignService;
    @Resource
    private PaymentMerchantPlatformService paymentMerchantPlatformService;


    @Override
    public Result<UnifiedOrderResBO> unifiedOrder(UnifiedOrderBO unifiedOrderBO) throws BusinessException {
        Assert.isTrue(null != unifiedOrderBO.getAmount(), "订单支付总金额有误");
        // 子订单商品信息-商品维度清分
        List<UnifiedOrderResBO.SubOrder> subOrders = new ArrayList<>();
        unifiedOrderBO.getSubOrders().forEach(subOrderBO -> {
            UmsUnifiedOrderParam.UmsProduct umsProduct = new UmsUnifiedOrderParam.UmsProduct();
            umsProduct.setGoodsId(subOrderBO.getProductCode());
            // TODO 微信、支付宝支付需要限制商品id不超过32位
            umsProduct.setGoodsId(CommonUtil.subString(subOrderBO.getProductCode(), 32));
            umsProduct.setGoodsName(CommonUtil.orderNameHandle(subOrderBO.getProductName()));
            umsProduct.setQuantity(subOrderBO.getProductCount());
            umsProduct.setPrice(subOrderBO.getAmount()); // 传实付金额
            umsProduct.setSubMerchantId(subOrderBO.getSubMerchantId());
            umsProduct.setMerOrderId(subOrderBO.getSubFlowId());
            umsProduct.setSubOrderAmount(subOrderBO.getAmount());
            UnifiedOrderResBO.SubOrder subOrder = ObjectConvertUtil.convert(umsProduct, UnifiedOrderResBO.SubOrder.class).get();
            subOrder.setEnterpriseCode(subOrderBO.getEnterpriseCode());
            subOrder.setSubOrderId(subOrderBO.getSubOrderId());
            subOrders.add(subOrder);
        });
        Assert.isTrue(null != unifiedOrderBO.getAmount(), "订单支付总金额有误");
        UnifiedOrderResBO unifiedOrderResBO = new UnifiedOrderResBO();
        unifiedOrderResBO.setSubOrders(subOrders);
        PaymentWayEnum paymentWayEnum = PaymentWayEnum.getByCode(unifiedOrderBO.getPayWay()).get();
        Result<UnifiedOrderResBO> result = new Result<>();
        try {
            switch (paymentWayEnum) {
                case WECHAT -> {
                    // 微信支付
                    Asserts.isNotEmpty(unifiedOrderBO.getSubAppId(), "高诚支付中台：微信支付必传微信appId！");
                    Asserts.isNotEmpty(unifiedOrderBO.getOpenid(), "高诚支付中台：微信支付必传微信openId！");
                    Asserts.isNotEmpty(unifiedOrderBO.getSubAppId(), "高诚支付中台：微信支付必传微信appId！");
                    GcWxPayReq req = new GcWxPayReq();
                    //req.setTypeCode("JSPAY");
                    req.setAppid(unifiedOrderBO.getSubAppId());
                    req.setOpenid(unifiedOrderBO.getOpenid());
                    if (null == unifiedOrderBO.getPayExpiryTime()) {
                        // 没有设置过期时间的情况，默认21分钟后过期（订单中心给的默认值）
                        unifiedOrderBO.setPayExpiryTime(LocalDateTime.now().plusMinutes(21));
                    }
                    req.setOrderTimeoutDate(DateTimeUtil.formatter(unifiedOrderBO.getPayExpiryTime(), DateTimeUtil.fmt_yyyyMMddHHmmss));
                    req.setMoney(AmountUtils.amount2Yuan(unifiedOrderBO.getAmount()));
                    req.setOrderNo(unifiedOrderBO.getFlowId());
                    req.setMoney(AmountUtils.amount2Yuan(unifiedOrderBO.getOrderAmount()));
                    req.setDescription(unifiedOrderBO.getOrderName());
                    GcBaseResp<GcWxPayRes> wxPayResult = new GcPayChannel(initGcPayConfig(unifiedOrderBO.getOrgPaymentChannelId())).wechatPay(req);
                    unifiedOrderResBO.setOutTradeNo(wxPayResult.getData().getTradeNo());
                    unifiedOrderResBO.setTransactionId(wxPayResult.getData().getTradeNo());
                    unifiedOrderResBO.setPayInfo(JsonUtil.toJsonString(JsonUtil.fromJson(wxPayResult.getData().getPayData(), WechatPayResBO.class)));
                }
                // 处理相响应结果
                case ALIPAY -> {
                    // 支付宝支付
                    Asserts.isNotEmpty(unifiedOrderBO.getOpenid(), "高诚支付中台：支付宝支付必传支付宝用户id！");
                    Asserts.isNotEmpty(unifiedOrderBO.getSubAppId(), "高诚支付中台：微信支付必传微信appId！");
                    GcAliPayReq aliPayReq = new GcAliPayReq();
                    //req.setTypeCode("ALI_CREATE");
                    //req.setUserid(unifiedOrderBO.getOpenid());
                    if (null == unifiedOrderBO.getPayExpiryTime()) {
                        // 没有设置过期时间的情况，默认21分钟后过期（订单中心给的默认值）
                        unifiedOrderBO.setPayExpiryTime(LocalDateTime.now().plusMinutes(21));
                    }
                    // 订单过期时间，1m=1分钟
                    Duration duration = Duration.between(LocalDateTime.now(), unifiedOrderBO.getPayExpiryTime());
                    long minutes = duration.toMinutes();
                    aliPayReq.setTimeoutExpress(minutes + "m");
                    // 设置基础信息，并签名
                    aliPayReq.setMoney(AmountUtils.amount2Yuan(unifiedOrderBO.getAmount()));
                    aliPayReq.setOrderNo(unifiedOrderBO.getFlowId());
                    aliPayReq.setMoney(AmountUtils.amount2Yuan(unifiedOrderBO.getOrderAmount()));
                    aliPayReq.setDescription(unifiedOrderBO.getOrderName());
                    //BeanUtils.copyProperties(jsonResult, aliPayResult);
                    GcBaseResp<GcAliPayRes> aliPayResult = new GcPayChannel(initGcPayConfig(unifiedOrderBO.getOrgPaymentChannelId())).aliPay(aliPayReq);
                    // 处理相响应结果
                    unifiedOrderResBO.setOutTradeNo(aliPayResult.getData().getTradeNo());
                    unifiedOrderResBO.setTransactionId(aliPayResult.getData().getTradeNo());
                    unifiedOrderResBO.setPayInfo(JsonUtil.toJsonString(new AlipayResBO(aliPayResult.getData().getTradeNo(),null)));
                }
                case CORPPAY -> {
                    // 支付宝支付
                    GcCorppayReq corppayReq = new GcCorppayReq();
                    //req.setTypeCode("ALI_CREATE");
                    //req.setUserid(unifiedOrderBO.getOpenid());
                    if (null == unifiedOrderBO.getPayExpiryTime()) {
                        // 没有设置过期时间的情况，默认21分钟后过期（订单中心给的默认值）
                        unifiedOrderBO.setPayExpiryTime(LocalDateTime.now().plusMinutes(30));
                    }
                    // 订单过期时间，1m=1分钟
                    corppayReq.setOrderTimeoutDate(DateTimeUtil.formatter(unifiedOrderBO.getPayExpiryTime(), DateTimeUtil.fmt_yyyyMMddHHmmss));
                    // 设置基础信息，并签名
                    corppayReq.setMoney(AmountUtils.amount2Yuan(unifiedOrderBO.getAmount()));
                    corppayReq.setOrderNo(unifiedOrderBO.getFlowId());
                    corppayReq.setMoney(AmountUtils.amount2Yuan(unifiedOrderBO.getOrderAmount()));
                    corppayReq.setDescription(unifiedOrderBO.getOrderName());
                    GcBaseResp<GcCorppayRes> corpPayResult = new GcPayChannel(initGcPayConfig(unifiedOrderBO.getOrgPaymentChannelId())).corpPay(corppayReq);
                    // 处理相响应结果
                    unifiedOrderResBO.setOutTradeNo(corpPayResult.getData().getTradeNo());
                    unifiedOrderResBO.setTransactionId(corpPayResult.getData().getTradeNo());
                    unifiedOrderResBO.setPayInfo(JsonUtil.toJsonString(new CorpPayRes(corpPayResult.getData().getPayUrl())));
                }
            }
            result.setData(unifiedOrderResBO);
            result.setRet(0);
            result.setMsg("高诚统一支付下单成功");
            return result;
        } catch (BusinessException e) {
            log.error(e.getMessage());
            result.setRet(1);
            result.setMsg("高诚统一支付下单失败:" + e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage());
            result.setRet(1);
            result.setMsg("高诚统一支付下单失败!");
        }
        return result;
    }

    @Override
    public Result<GetUnifiedOrderResBO> get(GetUnifiedOrderBO getUnifiedOrderBO) throws BusinessException {
        QueryWrapper<PaymentOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("flow_id", getUnifiedOrderBO.getOrderId());
        queryWrapper.eq("user_id", getUnifiedOrderBO.getUid());
        PaymentOrder paymentOrder = paymentOrderMapper.selectOne(queryWrapper);
        Assert.isTrue(null != paymentOrder, "未查询到相应流水");
        Assert.isTrue(!StringUtils.isEmpty(paymentOrder.getPaymentWay()), "流水支付方式异常");
        final GcPayProperties properties = gcPayConfig.getByOrgPayChannelId(getUnifiedOrderBO.getOrgPaymentChannelId());

        GcOrderQueryReq params = new GcOrderQueryReq();
        params.setAccessId(properties.getAccessId());
        params.setMchNo(properties.getMchNo());
        params.setOrderNo(paymentOrder.getFlowId());
        // 执行签名
        Result<GetUnifiedOrderResBO> result = new Result<>();
        try {
            GcBaseResp<GcOrderQueryRes> orderQueryResult = new GcPayChannel(initGcPayConfig(getUnifiedOrderBO.getOrgPaymentChannelId())).queryPay(params);
            log.info("高诚统一支付查询返回:{}", JsonUtil.toJsonString(orderQueryResult));
            // 处理相响应结果
            // 处理响应结果
            result.setRet(orderQueryResult.isOk() ? 0 : 1);
            result.setMsg(StringUtils.isNotEmpty(orderQueryResult.getMessage()) ? orderQueryResult.getMessage() : "");

            GetUnifiedOrderResBO getUnifiedOrderResBO = new GetUnifiedOrderResBO();
            getUnifiedOrderResBO.setOrderId(getUnifiedOrderBO.getOrderId());
            getUnifiedOrderResBO.setTransactionId(paymentOrder.getTransactionId());
            getUnifiedOrderResBO.setTradeNo(paymentOrder.getTradeNo());

            // 订单状态处理
            Integer tradeStatus = orderQueryResult.getData().getTradeStatus();
            if (tradeStatus == 0) {
                getUnifiedOrderResBO.setOrderStatus(ChannelOrderStatusEnum.fail);
            } else if (tradeStatus == 1) {
                getUnifiedOrderResBO.setOrderStatus(ChannelOrderStatusEnum.success);
            } else if (tradeStatus == -1) {
                getUnifiedOrderResBO.setOrderStatus(ChannelOrderStatusEnum.wait);
            }
            if (null != orderQueryResult.getData() && StringUtils.isNotEmpty(orderQueryResult.getData().getTradeTime())) {
                getUnifiedOrderResBO.setPayTime(DateTimeUtil.string2LocalDateTime(orderQueryResult.getData().getTradeTime(), "yyyy-MM-dd HH:mm:ss"));
            }
            if (null != orderQueryResult.getData() && StringUtils.isNotEmpty(orderQueryResult.getData().getPayedMoney())) {
                Integer payAmount = AmountUtils.yuan2Amount(orderQueryResult.getData().getPayedMoney());
                getUnifiedOrderResBO.setAmount(payAmount);
            }
            result.setData(getUnifiedOrderResBO);
        } catch (BusinessException e) {
            log.error(e.getMessage());
            result.setRet(1);
            result.setMsg("高诚统一支付查询订单失败:" + e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage());
            result.setRet(1);
            result.setMsg("高诚统一支付查询订单失败!");
        }
        return result;
    }

    @Override
    public Result<RefundOrderResBO> refund(RefundOrderBO refundOrderBO) throws BusinessException {
        QueryWrapper<PaymentOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("flow_id", refundOrderBO.getOrderId());
        PaymentOrder paymentOrder = paymentOrderMapper.selectOne(queryWrapper);
        Assert.isTrue(null != paymentOrder, "未查询到相应流水");
        Assert.isTrue(!StringUtils.isEmpty(paymentOrder.getPaymentWay()), "流水支付方式异常");
        final GcPayProperties properties = gcPayConfig.getByOrgPayChannelId(refundOrderBO.getOrgPaymentChannelId());

        // 查询退款明细列表
        List<PaymentRefundFlowDetail> refundFlowDetails = refundFlowDetailMapper.selectList(new LambdaQueryWrapper<PaymentRefundFlowDetail>().eq(PaymentRefundFlowDetail::getFlowId, refundOrderBO.getRefundId())
                .in(PaymentRefundFlowDetail::getSubFlowId, refundOrderBO.getSubOrders().stream().map(RefundOrderBO.SubOrderBO::getSubRefundId).collect(Collectors.toList())));
        // 退款明细对应的支付明细列表
        List<PaymentFlowDetail> paymentFlowDetails = paymentFlowDetailMapper.selectList(new LambdaQueryWrapper<PaymentFlowDetail>().eq(PaymentFlowDetail::getFlowId, paymentOrder.getFlowId())
                .in(PaymentFlowDetail::getSubFlowId, refundFlowDetails.stream().map(PaymentRefundFlowDetail::getSubPayFlowId).toList()));
        // 计算退分账信息，key是清分规则编码，第一位是类型M-商户，P-是商品
        Map<String, SettlementRuleResVO> merchantRuleMap = settlePlatformService.querySettleRules(paymentFlowDetails.stream().map(PaymentFlowDetail::getSettleRuleCode).collect(Collectors.toSet()));
        BusinessErrorInfoEnum.CHANNEL_PAY_FAIL.assertIsTrue(null != merchantRuleMap && merchantRuleMap.size() > 0);

        // 2、查询商户企业用户号
        List<MerchantChannelResponseDTO> merRepResult = paymentMerchantPlatformService.queryByMerchantCodeAndChannel(paymentFlowDetails.stream().map(d -> {
            final MerchantChannelRequestDTO merchantChannelRequestDTO = new MerchantChannelRequestDTO();
            merchantChannelRequestDTO.setBusinessCode(paymentOrder.getBusinessCode());
            merchantChannelRequestDTO.setOrgPaymentChannelId(paymentOrder.getOrgPaymentChannelId());
            merchantChannelRequestDTO.setPaymentChannelCode(paymentOrder.getPaymentChannel());
            merchantChannelRequestDTO.setMerchantCode(d.getMerchantCode());
            return merchantChannelRequestDTO;
        }).collect(Collectors.toList()));
        Asserts.isTrue(CollectionUtils.isEmpty(merRepResult), "高诚支付订单退款失败，缺少子商户配置！");
        final Result<List<MerchantChannelResponseDTO>> orgSubMerchants = merchantFeignService.queryOrgSubMerchant(Collections.singletonList(paymentOrder.getOrgPaymentChannelId()));
        Asserts.isTrue(CollectionUtils.isNotEmpty(orgSubMerchants.getData()), "未配置平台收款子商户号，请联系研发处理！");
        final Map<Long, MerchantChannelResponseDTO> orgSubMerchantsMap = orgSubMerchants.getData().stream().collect(Collectors.toMap(MerchantChannelResponseDTO::getOrgPaymentChannelId, Function.identity(), (k1, k2) -> k2));
        // 提交的退款明细
        // 退佣金明细
        List<GcPaySplitAccReq> splitAcc = new ArrayList<>();
        for (RefundOrderBO.SubOrderBO subOrder : refundOrderBO.getSubOrders()) {
            PaymentRefundFlowDetail refundDetail = refundFlowDetails.stream().filter(rfd -> rfd.getSubFlowId().equals(subOrder.getSubRefundId())).findFirst().get();
            PaymentFlowDetail flowDetail = paymentFlowDetails.stream().filter(fd -> fd.getSubFlowId().equals(refundDetail.getSubPayFlowId())).findFirst().get();
            // 申请退款金额
            Integer refundAmount = refundDetail.getRefundAmount();
            SettlementRuleResVO ruleResVO = merchantRuleMap.get(flowDetail.getSettleRuleCode());
            Asserts.isTrue(null != ruleResVO, "未查询到清分规则配置，请联系管理员处理！");
            // 计算平台返还佣金金额
            final int platformAmount = settlePlatformService.platformAmountCommissionMerchantSettleRule(refundAmount, ruleResVO);
            if (platformAmount > 0) {
                // 平台佣金
                GcPaySplitAccReq gcPaySplitAccReq = new GcPaySplitAccReq();
                MerchantChannelResponseDTO merchantChannelResponseDTO = orgSubMerchantsMap.get(paymentOrder.getOrgPaymentChannelId());
                gcPaySplitAccReq.setMchNo(merchantChannelResponseDTO.getSubMchId());
                gcPaySplitAccReq.setAmt(AmountUtils.amount2Yuan(platformAmount));
                splitAcc.add(gcPaySplitAccReq);
            }
            // 商户返还佣金金额
            GcPaySplitAccReq gcPaySplitAccReq = new GcPaySplitAccReq();
            Optional<MerchantChannelResponseDTO> first = merRepResult.stream().filter(m -> m.getMerchantCode().equals(flowDetail.getMerchantCode())).findFirst();
            Asserts.isTrue(first.isPresent() && StringUtils.isNotEmpty(first.get().getSubMchId()), "未查询到子商户清分商户配置，请联系管理员处理！");

            gcPaySplitAccReq.setMchNo(first.get().getSubMchId());
            gcPaySplitAccReq.setAmt(AmountUtils.amount2Yuan(refundDetail.getRefundAmount() - platformAmount));
            splitAcc.add(gcPaySplitAccReq);
        }

        Result<RefundOrderResBO> result = new Result<>();
        try {
            GcRefundReq params = new GcRefundReq();
            params.setAccessId(properties.getAccessId());
            params.setMchNo(properties.getMchNo());
            params.setOrderNo(paymentOrder.getFlowId());
            params.setRefOrderNo(refundOrderBO.getRefundId());
            params.setMoney(AmountUtils.amount2Yuan(refundOrderBO.getAmount()));
            // 退款类型：1 退货退款，2 仅退款，3 换货退款
            params.setType(1);
            params.setRemark(refundOrderBO.getReason());
            params.setMobile(paymentOrder.getUserTel());

            GcBaseResp<GcOrderRefundRes> orderRefundResult = new GcPayChannel(initGcPayConfig(refundOrderBO.getOrgPaymentChannelId())).refund(params);
            // 订单状态处理
            // Asserts.isTrue(orderRefundResult.getData().getRefTradeStatus().equals(0) ||orderRefundResult.getData().getRefTradeStatus().equals(1),"高诚交易平台【订单退款】失败!");
            // 处理响应结果
            result.setRet(orderRefundResult.isOk() ? 0 : 1);
            result.setMsg(StringUtils.isNotEmpty(orderRefundResult.getMessage()) ? orderRefundResult.getMessage() : "");
            RefundOrderResBO refundOrderResBO = new RefundOrderResBO();

            if (orderRefundResult.getData().getRefTradeStatus().equals(0)) {
                result.setRet(1);
                result.setMsg(StringUtils.isNotEmpty(result.getMsg()) ? result.getMsg() : "高诚交易平台【订单退款】返回退款失败！");
            }
            result.getData().setRefundTypeEnum(ChannelRefundTypeEnum.ALL);
        } catch (BusinessException e) {
            log.error("高诚统一支付【退款】失败:", e);
            result.setRet(1);
            result.setMsg("高诚统一支付【退款】失败:" + e.getMessage());
        } catch (Exception e) {
            log.error("高诚统一支付【退款】失败:", e);
            result.setRet(1);
            result.setMsg("高诚统一支付【退款】失败!");
        }
        return result;
    }

    @Override
    public Result<GetRefundOrderResBO> getRefund(GetRefundOrderBO getRefundOrderBO) throws BusinessException {

        QueryWrapper<PaymentRefundFlow> conditions = new QueryWrapper<>();
        conditions.eq("user_id", getRefundOrderBO.getUid());
        conditions.eq("flow_id", getRefundOrderBO.getRefundId());
        PaymentRefundFlow refundFlow = paymentRefundFlowMapper.selectOne(conditions);
        Assert.isTrue(null != refundFlow, "未查询到相应退款流水");

        QueryWrapper<PaymentOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("flow_id", refundFlow.getPayFlowId());
        queryWrapper.eq("user_id", getRefundOrderBO.getUid());
        PaymentOrder paymentOrder = paymentOrderMapper.selectOne(queryWrapper);
        Assert.isTrue(null != paymentOrder, "未查询到相应支付流水");
        Assert.isTrue(!StringUtils.isEmpty(paymentOrder.getPaymentWay()), "流水支付方式异常");

        Assert.isTrue(null != paymentOrder, "未查询到相应流水");
        Assert.isTrue(!StringUtils.isEmpty(paymentOrder.getPaymentWay()), "流水支付方式异常");
        final GcPayProperties properties = gcPayConfig.getByOrgPayChannelId(getRefundOrderBO.getOrgPaymentChannelId());

        String queryUrl = properties.getHost() + "/oapi/s2/pay/order/refund/status";
        GcQueryRefundReq params = new GcQueryRefundReq();
        params.setAccessId(properties.getAccessId());
        params.setMchNo(properties.getMchNo());
        params.setOrderNo(paymentOrder.getFlowId());
        params.setRefOrderNo(refundFlow.getFlowId());
        // 执行签名
        GcSignUtils.doSign(params, properties);
        log.info("gc_query_refund_order_url:{}, params:{}", queryUrl, JsonUtil.toJsonString(params));
        Result<GetRefundOrderResBO> result = new Result<>();
        try {
            GcBaseResp<GcOrderRefundQueryRes> refundOrderQueryRes = new GcPayChannel(initGcPayConfig(getRefundOrderBO.getOrgPaymentChannelId())).queryRefund(params);
            // 处理响应结果
            result.setRet(refundOrderQueryRes.isOk() ? 0 : 1);
            result.setMsg(StringUtils.isNotEmpty(refundOrderQueryRes.getMessage()) ? refundOrderQueryRes.getMessage() : "");

            GetRefundOrderResBO refundOrderResBO = new GetRefundOrderResBO();
            refundOrderResBO.setRefundId(getRefundOrderBO.getRefundId());
            refundOrderResBO.setTransactionId(paymentOrder.getTransactionId());
            refundOrderResBO.setTradeNo(paymentOrder.getTradeNo());

            // 订单状态处理
            Integer tradeStatus = refundOrderQueryRes.getData().getRefTradeStatus();
            if (tradeStatus == 0) {
                //退款未成功
                refundOrderResBO.setChannelOrderStatusEnum(ChannelOrderStatusEnum.fail);
            } else if (tradeStatus == 1) {
                //退款成功
                refundOrderResBO.setChannelOrderStatusEnum(ChannelOrderStatusEnum.success);
            } else if (tradeStatus == -1) {
                //-1-未知（退款中）
                refundOrderResBO.setChannelOrderStatusEnum(ChannelOrderStatusEnum.ing);
            }
            result.setData(refundOrderResBO);
        } catch (BusinessException e) {
            log.error(e.getMessage());
            result.setRet(1);
            result.setMsg("高诚统一支付【退款订单查询】失败:" + e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage());
            result.setRet(1);
            result.setMsg("高诚统一支付【退款订单查询】失败!");
        }
        return null;
    }

    @Override
    public Result close(CloseOrderBO closeOrderBO) throws BusinessException {
        return null;
    }

    @Override
    public PayResultBO payResult(Map<String, Object> payResult) {
        if (MapUtils.isEmpty(payResult)) {
            return null;
        }
        final GaoChengPayNotifyReq gaoChengPayNotifyReq = JsonUtil.fromJson(payResult, new TypeReference<GaoChengPayNotifyReq>() {
        });
        PayResultBO payResultBO = new PayResultBO();
        if (StringUtils.isNotEmpty(gaoChengPayNotifyReq.getTradeTime())) {
            // 高诚返回的是:yyyyMMddHHmmss
            payResultBO.setPayTime(DateTimeUtil.string2LocalDateTime(gaoChengPayNotifyReq.getTradeTime(), DateTimeUtil.fmt_yyyyMMddHHmmss));
        } else {
            payResultBO.setPayTime(LocalDateTime.now());
        }

        payResultBO.setAmount(AmountUtils.yuan2Amount(gaoChengPayNotifyReq.getPayedMoney()));
        payResultBO.setOrderId(gaoChengPayNotifyReq.getOrderNo());
        payResultBO.setStatus("success");
        return payResultBO;
    }

    @Override
    public RefundResultBO refundResult(Map<String, Object> refundResult) {
        return null;
    }

    @Override
    public Result settleV2(List<PaymentFlowDetailSettle> detailSettles, List<PaymentFlowDetailSettleDetail> detailSettlesDetails) throws BusinessException {
        return Result.success();
    }

    @Override
    public boolean autoQueryStatus(Long orgPaymentChannelId) {
        final GcPayProperties gcPayProperties = gcPayConfig.getByOrgPayChannelId(orgPaymentChannelId);
        return gcPayProperties.autoQueryStatus();
    }

    @Override
    public PayOrderAutoQueryConfig getOrderAutoQueryConfig(Long orgPaymentChannelId) {
        final GcPayProperties gcPayProperties = gcPayConfig.getByOrgPayChannelId(orgPaymentChannelId);
        if (Objects.isNull(gcPayProperties) || Objects.isNull(gcPayProperties.getQueryStatusConfig())) {
            return null;
        }
        return gcPayProperties.getQueryStatusConfig();
    }

    @Override
    public PaymentChannelEnum getPaymentChannelEnum() {
        return PaymentChannelEnum.gao_cheng_nong_hang;
    }

    /**
     * @param subSettles 结算明细
     * @return
     */
    private List<GcPaySplitAccReq> getSettleList(List<UnifiedOrderSettleBO> subSettles) {
        List<GcPaySplitAccReq> splitAcc = new ArrayList<>();
        List<UnifiedOrderSettleBO.UnifiedOrderSettleItemBO> settleItems = new ArrayList<>();
        for (UnifiedOrderSettleBO subSettle : subSettles) {
            settleItems.addAll(subSettle.getSettleItems());
        }
        settleItems.stream().collect(Collectors.groupingBy(UnifiedOrderSettleBO.UnifiedOrderSettleItemBO::getMid)).forEach((subMerchantId, items) -> {
            GcPaySplitAccReq item = new GcPaySplitAccReq();
            item.setMchNo(subMerchantId);
            item.setAmt(AmountUtils.amount2Yuan(items.stream().mapToInt(UnifiedOrderSettleBO.UnifiedOrderSettleItemBO::getTotalAmount).sum()));
            splitAcc.add(item);
        });
        return splitAcc;
    }

    private GcPayProperties initGcPayConfig(Long orgPaymentChannelId){
        return gcPayConfig.getByOrgPayChannelId(orgPaymentChannelId);
    }


}
